package com.yyh.synctool.server.aspect;

import com.yyh.pojo.SyncParam;
import com.yyh.result.JsonResult;
import com.yyh.synctool.server.exception.IllegalIdentityException;
import com.yyh.synctool.server.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 用于同步请求的身份进行验证
 * @author xuan
 * @date 2021/12/17
 */
@Slf4j
@Aspect
@Component
public class AuthAspect
{
    private AuthService authService;

    public AuthAspect(AuthService authService) {
        this.authService = authService;
    }


    /** 切入点：所有公开的的服务方法 */
    @Pointcut("execution(public * com.yyh.synctool.server.service.impl.ProviderServiceImpl.*(..))")
    public void pointForServices() {
    }

    /**
     * 环绕通知
     * 可以决定目标方法是否执行
     * 什么时候执行
     * 执行时是否需要替换方法参数
     * 执行完毕是否需要替换返回值。
     *
     * 环绕通知执行先于前置通知
     * 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
     * @param proceedingJoinPoint
     */
    @Around("pointForServices()")
    public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.debug("环绕通知的目标方法名：{}", proceedingJoinPoint.getSignature().toString());

        Object[] args = proceedingJoinPoint.getArgs();
        for (Object arg : args) {
            if (arg.getClass().isAssignableFrom(SyncParam.class)) {
                SyncParam syncParam = (SyncParam) arg;
                String gsid = syncParam.getGsid();
                String credential = syncParam.getCredential();
                log.debug("验证身份：gsid={}；credential={}。", gsid, credential);

                // 验证身份
                if (authService.authorize(gsid, credential)) {
                    log.debug("通过验证：gsid={}；credential={}。", gsid, credential);
                    Object ret = proceedingJoinPoint.proceed();
                    return ret;
                } else {
                    // 未通过身份验证
                    throw new IllegalIdentityException("未通过验证，gsid="+gsid+"；credential="+credential+"。");
                }
            }
        }

        return null;
    }

}
